package edu.nf.llmtest.common.aspect;

import edu.nf.llmtest.common.annotation.SyncData;
import edu.nf.llmtest.common.enumeration.ActionType;
import edu.nf.llmtest.common.enumeration.TargetType;
import edu.nf.llmtest.common.sync.DataSyncStrategy;
import edu.nf.llmtest.common.sync.syncableService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * @ Author bin
 * @ Create  2025/10/28 下午8:07
 **/
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class DataSyncAspect {
    private final List<DataSyncStrategy<?>> strategies;

    @Pointcut("@annotation(edu.nf.llmtest.common.annotation.SyncData)")
    public void syncPointcut() {}

    @AfterReturning(pointcut = "syncPointcut() && @annotation(syncAnno)", returning = "result")
    public void afterSync(JoinPoint jp, SyncData syncAnno, Object result) {
        Object target = jp.getTarget();
        Object entity = resolveEntity(target, jp.getArgs(), result);
        if (entity == null) {
            log.warn("未找到可同步的实体");
            return;
        }

        ActionType action = syncAnno.action();
        List<TargetType> targets = Arrays.asList(syncAnno.targets());
        Class<?> entityClass = entity.getClass();

        log.info("同步触发: {} {} -> {}", action, entityClass.getSimpleName(), targets);

        for (DataSyncStrategy<?> strategy : strategies) {
            if (!strategy.supports(entityClass)) continue;
            executeStrategy(strategy, entity, action, targets);
        }
    }

    private void executeStrategy(DataSyncStrategy strategy, Object entity, ActionType action, List<TargetType> targets) {
        try {
            switch (action) {
                case CREATE:
                case UPDATE:
                    if (targets.contains(TargetType.REDIS)) strategy.syncToRedis(entity);
                    if (targets.contains(TargetType.ES)) strategy.syncToES(entity);
                    break;
                case DELETE:
                    if (targets.contains(TargetType.REDIS)) strategy.deleteFromRedis(entity);
                    if (targets.contains(TargetType.ES)) strategy.deleteFromES(entity);
                    break;
            }
        } catch (Exception e) {
            log.error("同步执行失败: {}", e.getMessage(), e);
        }
    }

    private Object resolveEntity(Object target, Object[] args, Object result) {
        // 1. 优先返回值
        if (result != null) return result;

        // 2. 参数中查找
        for (Object arg : args) {
            if (arg != null && isEntity(arg)) {
                return arg;
            }
        }

        // 3. 从泛型接口类型构造
        if (target instanceof syncableService) {
            Class<?> entityClass = ((syncableService<?>) target).getEntityClass();
            return tryConstructEntity(entityClass, args);
        }
        return null;
    }

    private boolean isEntity(Object obj) {
        return obj.getClass().getPackageName().contains("model.entity");
    }

    private Object tryConstructEntity(Class<?> clazz, Object[] args) {
        try {
            Object instance = clazz.getDeclaredConstructor().newInstance();
            for (Object arg : args) {
                if (arg instanceof String && ((String) arg).contains("@")) {
                    clazz.getMethod("setEmail", String.class).invoke(instance, arg);
                }
            }
            return instance;
        } catch (Exception e) {
            log.warn("无法构造实体: {}", e.getMessage());
            return null;
        }
    }
}
